<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>IPC之十三：使用libdbus通过D-Bus请求系统调用实现域名解析的实例 - whowin - 发表我个人原创作品的技术博客</title>
  <meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>

<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />

<meta name="theme-color" content="#f8f5ec" />
<meta name="msapplication-navbutton-color" content="#f8f5ec">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="#f8f5ec">


<meta name="author" content="whowin" /><meta name="description" content="前面两篇有关 D-Bus 的文章介绍了使用 libdbus 库进行进程间的方法调用和信号的传输，实际上 D-Bus 的更强大的地方是其建立了与大量系统服务之间建立了有效的对话规范，使得应用程序可以使用标准的方式调用系统服务的方法，访问系统服务中的一些开放的属性，本文将使用 libdbus 库调用系统服务中的方法从而实现域名解析，本文给出了实现该功能的实例，附有完整的源代码；本文实例在 Ubuntu 20.04 上编译测试通过，gcc版本号为：9.4.0；本文不适合 Linux 编程的初学者阅读。
" /><meta name="keywords" content="linux, socket, hugo, dos" />






<meta name="generator" content="Hugo 0.97.3 with theme even" />


<link rel="canonical" href="https://whowin.gitee.io/post/blog/ipc/0023-dbus-resolve-hostname/" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">



<link href="/sass/main.min.e3fea119b1980e848b03dffbeddb11dd0fba483eed0e5f11870fb8e31f145bbd.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.1.20/dist/jquery.fancybox.min.css" integrity="sha256-7TyXnr2YU040zfSP+rEcz29ggW4j56/ujTPwjMzyqFY=" crossorigin="anonymous">


<meta property="og:title" content="IPC之十三：使用libdbus通过D-Bus请求系统调用实现域名解析的实例" />
<meta property="og:description" content="前面两篇有关 D-Bus 的文章介绍了使用 libdbus 库进行进程间的方法调用和信号的传输，实际上 D-Bus 的更强大的地方是其建立了与大量系统服务之间建立了有效的对话规范，使得应用程序可以使用标准的方式调用系统服务的方法，访问系统服务中的一些开放的属性，本文将使用 libdbus 库调用系统服务中的方法从而实现域名解析，本文给出了实现该功能的实例，附有完整的源代码；本文实例在 Ubuntu 20.04 上编译测试通过，gcc版本号为：9.4.0；本文不适合 Linux 编程的初学者阅读。" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://whowin.gitee.io/post/blog/ipc/0023-dbus-resolve-hostname/" /><meta property="article:section" content="post" />
<meta property="article:published_time" content="2023-12-10T16:43:29+08:00" />
<meta property="article:modified_time" content="2023-12-10T16:43:29+08:00" />

<meta itemprop="name" content="IPC之十三：使用libdbus通过D-Bus请求系统调用实现域名解析的实例">
<meta itemprop="description" content="前面两篇有关 D-Bus 的文章介绍了使用 libdbus 库进行进程间的方法调用和信号的传输，实际上 D-Bus 的更强大的地方是其建立了与大量系统服务之间建立了有效的对话规范，使得应用程序可以使用标准的方式调用系统服务的方法，访问系统服务中的一些开放的属性，本文将使用 libdbus 库调用系统服务中的方法从而实现域名解析，本文给出了实现该功能的实例，附有完整的源代码；本文实例在 Ubuntu 20.04 上编译测试通过，gcc版本号为：9.4.0；本文不适合 Linux 编程的初学者阅读。"><meta itemprop="datePublished" content="2023-12-10T16:43:29+08:00" />
<meta itemprop="dateModified" content="2023-12-10T16:43:29+08:00" />
<meta itemprop="wordCount" content="4865">
<meta itemprop="keywords" content="Linux,进程间通信,D-Bus,libdbus,IPC,域名解析,systemd-resolved," /><meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="IPC之十三：使用libdbus通过D-Bus请求系统调用实现域名解析的实例"/>
<meta name="twitter:description" content="前面两篇有关 D-Bus 的文章介绍了使用 libdbus 库进行进程间的方法调用和信号的传输，实际上 D-Bus 的更强大的地方是其建立了与大量系统服务之间建立了有效的对话规范，使得应用程序可以使用标准的方式调用系统服务的方法，访问系统服务中的一些开放的属性，本文将使用 libdbus 库调用系统服务中的方法从而实现域名解析，本文给出了实现该功能的实例，附有完整的源代码；本文实例在 Ubuntu 20.04 上编译测试通过，gcc版本号为：9.4.0；本文不适合 Linux 编程的初学者阅读。"/>

<!--[if lte IE 9]>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"></script>
<![endif]-->

<!--[if lt IE 9]>
  <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->

  <script async src="/js/busuanzi.pure.mini.js"></script><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9724909319263152"
     crossorigin="anonymous"></script>


</head>
<body>
  <div id="mobile-navbar" class="mobile-navbar">
  <div class="mobile-header-logo">
    <a href="/" class="logo">WhoWin</a>
  </div>
  <div class="mobile-navbar-icon">
    <span></span>
    <span></span>
    <span></span>
  </div>
</div>
<nav id="mobile-menu" class="mobile-menu slideout-menu">
  <ul class="mobile-menu-list">
    <a href="/">
        <li class="mobile-menu-item">首页</li>
      </a><a href="/post/">
        <li class="mobile-menu-item">文章归档</li>
      </a><a href="/article-categories/categories/">
        <li class="mobile-menu-item">文章分类</li>
      </a><a href="/tags/">
        <li class="mobile-menu-item">文章标签</li>
      </a><a href="/about/about/">
        <li class="mobile-menu-item">关于</li>
      </a>
  </ul>

  


</nav>

  <div class="container" id="mobile-panel">
    <header id="header" class="header">
        <div class="logo-wrapper">
  <a href="/" class="logo">WhoWin</a>
  
  <div style="position:absolute; left: 80px; top: 75px; color: crimson">
      ———开源和分享是技术发展的源泉和动力；本博客所有文章均为原创
  </div>
</div>





<nav class="site-navbar">
  <ul id="menu" class="menu">
    <li class="menu-item">
        <a class="menu-item-link" href="/">首页</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/post/">文章归档</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/article-categories/categories/">文章分类</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/tags/">文章标签</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/about/about/">关于</a>
      </li>
  </ul>
</nav>

    </header>

    <main id="main" class="main">
      <div class="content-wrapper">
        <div id="content" class="content">
          <article class="post">
    
    <header class="post-header">
      <h1 class="post-title">IPC之十三：使用libdbus通过D-Bus请求系统调用实现域名解析的实例</h1>

      <div class="post-meta">
        <span class="post-time"> 2023-12-10 </span>
        <div class="post-category">
            <a href="/categories/ipc/"> IPC </a>
            <a href="/categories/linux/"> Linux </a>
            <a href="/categories/c-language/"> C Language </a>
            <a href="/categories/network/"> Network </a>
            </div>
        
      </div>
    </header>

    <div class="post-toc" id="post-toc">
  <h2 class="post-toc-title">文章目录</h2>
  <div class="post-toc-content always-active">
    <nav id="TableOfContents">
  <ul>
    <li>
      <ul>
        <li><a href="#1-基本概念">1 基本概念</a></li>
        <li><a href="#2-systemd-resolved-介绍">2 systemd-resolved 介绍</a></li>
        <li><a href="#3-libdbus-中相关函数介绍">3 libdbus 中相关函数介绍</a>
          <ul>
            <li><a href="#函数-dbus_message_iter_init在一个消息上初始化一个迭代器">函数 <code>dbus_message_iter_init()</code>：在一个消息上初始化一个迭代器</a></li>
            <li><a href="#函数-dbus_message_iter_recurse在迭代器上初始化一个子迭代器">函数 <code>dbus_message_iter_recurse()</code>：在迭代器上初始化一个子迭代器；</a></li>
            <li><a href="#函数-dbus_message_iter_get_arg_type获取迭代器指向的参数的参数类型">函数 <code>dbus_message_iter_get_arg_type()</code>：获取迭代器指向的参数的参数类型；</a></li>
            <li><a href="#函数-dbus_message_iter_get_basic从消息迭代器读取基本类型值">函数 <code>dbus_message_iter_get_basic()</code>：从消息迭代器读取基本类型值</a></li>
            <li><a href="#函数-dbus_message_iter_next将迭代器移动到下一个字段">函数 <code>dbus_message_iter_next()</code>：将迭代器移动到下一个字段;</a></li>
            <li><a href="#使用迭代器获取参数的步骤">使用迭代器获取参数的步骤</a></li>
          </ul>
        </li>
        <li><a href="#4-域名解析实例">4 域名解析实例</a></li>
        <li><a href="#欢迎订阅-进程间通信专栏httpsblogcsdnnetwhowincategory_12404164html"><strong>欢迎订阅 <a href="https://blog.csdn.net/whowin/category_12404164.html">『进程间通信专栏』</a></strong></a></li>
      </ul>
    </li>
  </ul>
</nav>
  </div>
</div>
    <div class="post-content">
      <p>前面两篇有关 D-Bus 的文章介绍了使用 libdbus 库进行进程间的方法调用和信号的传输，实际上 D-Bus 的更强大的地方是其建立了与大量系统服务之间建立了有效的对话规范，使得应用程序可以使用标准的方式调用系统服务的方法，访问系统服务中的一些开放的属性，本文将使用 libdbus 库调用系统服务中的方法从而实现域名解析，本文给出了实现该功能的实例，附有完整的源代码；本文实例在 Ubuntu 20.04 上编译测试通过，gcc版本号为：9.4.0；本文不适合 Linux 编程的初学者阅读。</p>
<h2 id="1-基本概念">1 基本概念</h2>
<ul>
<li>
<p>阅读本文需要了解一些关于 D-Bus 的相关知识，以及 libdbus 库的基本使用方法，请阅读文章 <a href="https://whowin.gitee.io/post/blog/ipc/0021-ipc-using-dbus/">《IPC之十一：使用D-Bus实现客户端向服务端请求服务的实例》</a> 和 <a href="https://whowin.gitee.io/post/blog/ipc/0022-dbus-asyn-process-signal/">《IPC之十二：使用libdbus在D-Bus上异步发送/接收信号的实例》</a></p>
</li>
<li>
<p>上述两篇文章中，一篇文章介绍了服务端如何使用 libdbus 库在 D-Bus 上提供方法调用的服务，以及客户端如何向服务端请求调用方法的服务，另一篇文章中介绍了客户端如何使用 libdbus 库在 D-Bus 下异步接收信号，以及服务端如何发送信号；</p>
</li>
<li>
<p>其实，D-Bus 的一个重要功能是建立了客户端向系统服务请求服务的规范，使客户端可以借助系统服务提供的 API 快速完成某些功能；</p>
</li>
<li>
<p>本文将依托系统服务 <code>systemd-resolved</code> 提供的 API，使用 libdbus 库通过 D-Bus 调用 API，实现域名解析；</p>
</li>
<li>
<p>在终端上使用 <code>systemctl</code> 可以列出当前内存中的所有 systemd 服务，使用 <code>systemctl list-units systemd-resolved</code> 可以看到 <code>systemd-resolved</code> 服务当前的状态；</p>
<p><img src="https://whowin.gitee.io/images/190023/screenshot-of-systemctl.png" alt="Screenshot of systemctl"></p>
</li>
<li>
<p>通过 D-Bus 对一个系统服务中的一个方法进行调用与在应用层面对一个服务中的方法进行调用基本相同，请重点参考文章 <a href="https://whowin.gitee.io/post/blog/ipc/0021-ipc-using-dbus/">《IPC之十一：使用D-Bus实现客户端向服务端请求服务的实例》</a>，这里简单回顾以下；</p>
</li>
<li>
<p>首先要调用一个服务中的方法，要了解以下一些信息：</p>
<ol>
<li>总线名称</li>
<li>对象路径</li>
<li>接口名称</li>
<li>接口下的方法名称</li>
<li>调用接口的输入参数</li>
<li>调用完成后返回的参数</li>
</ol>
</li>
<li>
<p>在下一节介绍具体调用方法时，将一一找到上面这六条信息的答案；</p>
</li>
<li>
<p>在文章 <a href="https://whowin.gitee.io/post/blog/ipc/0021-ipc-using-dbus/">《IPC之十一：使用D-Bus实现客户端向服务端请求服务的实例》</a> 的实例中，我们用的是会话总线(Session Bus)，现在要调用系统服务，显然是要使用系统总线(System Bus)了，这是其中一点小区别；</p>
</li>
<li>
<p>在文章 <a href="https://whowin.gitee.io/post/blog/ipc/0021-ipc-using-dbus/">《IPC之十一：使用D-Bus实现客户端向服务端请求服务的实例》</a> 的实例中，我们使用 <code>dbus_message_append_args()</code> 向消息里添加参数，使用 <code>dbus_message_get_args()</code> 从回复消息里获取参数，在这个系统调用里，调用时的输入参数比较简单，我们仍然还可以使用 <code>dbus_message_append_args()</code>，但调用完成后的返回参数比较复杂，我们必须要引入一个迭代器(iterator)，这也是一个较大的区别，后面会有介绍；</p>
</li>
</ul>
<h2 id="2-systemd-resolved-介绍">2 systemd-resolved 介绍</h2>
<ul>
<li>
<p>systemd-resolved 在 D-Bus 上提供了一组用于解析 DNS 记录的 API，如下：</p>
<ol>
<li><code>ResolveHostname()</code> 用于解析主机名以获取其 IP 地址；</li>
<li><code>ResolveAddress()</code> 用于反向操作，获取 IP 地址的主机名；</li>
<li><code>ResolveService()</code> 用于解析 DNS-SD(DNS Service Discovery) 或 SRV 服务</li>
<li><code>ResolveRecord()</code> 用于解析任意资源记录</li>
</ol>
</li>
<li>
<p>关于这些 API 的说明，可以点击这里 <a href="https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.resolve1.html">org.freedesktop.resolve1 APIs</a></p>
</li>
<li>
<p>其实 glibc 中也是有类似的功能调用的，比如：getaddrinfo() 和 getnameinfo()；</p>
</li>
<li>
<p>本文中，将使用 <code>systemd-resolved</code> 的 <code>ResolveHostname()</code> 调用，获取一个主机名的 IP 地址；</p>
</li>
<li>
<p>先来看一下 <code>ResolveHostname</code> 方法在 <a href="https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.resolve1.html">官方文档</a> 上的原始定义：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">node /org/freedesktop/resolve1 {
</span></span><span class="line"><span class="cl">    interface org.freedesktop.resolve1.Manager {
</span></span><span class="line"><span class="cl">        methods:
</span></span><span class="line"><span class="cl">        ResolveHostname(in  i ifindex,
</span></span><span class="line"><span class="cl">                        in  s name,
</span></span><span class="line"><span class="cl">                        in  i family,
</span></span><span class="line"><span class="cl">                        in  t flags,
</span></span><span class="line"><span class="cl">                        out a(iiay) addresses,
</span></span><span class="line"><span class="cl">                        out s canonical,
</span></span><span class="line"><span class="cl">                        out t flags);
</span></span><span class="line"><span class="cl">        ......
</span></span><span class="line"><span class="cl">    }
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>根据 <a href="https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.resolve1.html">org.freedesktop.resolve1 APIs</a> 的说明：</p>
<ol>
<li>服务名称(总线名称)：<code>org.freedesktop.resolve1</code></li>
<li>对象路径：<code>/org/freedesktop/resolve1</code></li>
<li>接口名称：<code>org.freedesktop.resolve1.Manager</code></li>
<li>方法名称：<code>ResolveHostname</code></li>
</ol>
</li>
<li>
<p>关于方法调用的部分涉及到 D-Bus 的类型系统(Type System)，这部分在 <a href="https://dbus.freedesktop.org/doc/dbus-specification.html">D-Bus Specification</a> 中有详细的描述，这里把一些关键信息列出来</p>
<blockquote>
<p>普通数据类型</p>
</blockquote>
<table>
<thead>
<tr>
<th style="text-align:left">Conventional name</th>
<th style="text-align:center">ASCII type-code</th>
<th style="text-align:left">Encoding</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">BYTE</td>
<td style="text-align:center">y (121)</td>
<td style="text-align:left">Unsigned 8-bit integer</td>
</tr>
<tr>
<td style="text-align:left">BOOLEAN</td>
<td style="text-align:center">b (98)</td>
<td style="text-align:left">Boolean value: 0 is false, 1 is true, any other value allowed by the marshalling format is invalid</td>
</tr>
<tr>
<td style="text-align:left">INT16</td>
<td style="text-align:center">n (110)</td>
<td style="text-align:left">Signed (two&rsquo;s complement) 16-bit integer</td>
</tr>
<tr>
<td style="text-align:left">UINT16</td>
<td style="text-align:center">q (113)</td>
<td style="text-align:left">Unsigned 16-bit integer</td>
</tr>
<tr>
<td style="text-align:left">INT32</td>
<td style="text-align:center">i (105)</td>
<td style="text-align:left">Signed (two&rsquo;s complement) 32-bit integer</td>
</tr>
<tr>
<td style="text-align:left">UINT32</td>
<td style="text-align:center">u (117)</td>
<td style="text-align:left">Unsigned 32-bit integer</td>
</tr>
<tr>
<td style="text-align:left">INT64</td>
<td style="text-align:center">x (120)</td>
<td style="text-align:left">Signed (two&rsquo;s complement) 64-bit integer (mnemonic: x and t are the first characters in &ldquo;sixty&rdquo; not already used for something more common)</td>
</tr>
<tr>
<td style="text-align:left">UINT64</td>
<td style="text-align:center">t (116)</td>
<td style="text-align:left">Unsigned 64-bit integer</td>
</tr>
<tr>
<td style="text-align:left">DOUBLE</td>
<td style="text-align:center">d (100)</td>
<td style="text-align:left">IEEE 754 double-precision floating point</td>
</tr>
<tr>
<td style="text-align:left">UNIX_FD</td>
<td style="text-align:center">h (104)</td>
<td style="text-align:left">Unsigned 32-bit integer representing an index into an out-of-band array of file descriptors, transferred via some platform-specific mechanism (mnemonic: h for handle)</td>
</tr>
</tbody>
</table>
<blockquote>
<p>字符串类型</p>
</blockquote>
<table>
<thead>
<tr>
<th style="text-align:left">Conventional name</th>
<th style="text-align:center">ASCII type-code</th>
<th style="text-align:left">Validity constraints</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">STRING</td>
<td style="text-align:center">s (115)</td>
<td style="text-align:left">No extra constraints</td>
</tr>
<tr>
<td style="text-align:left">OBJECT_PATH</td>
<td style="text-align:center">o (111)</td>
<td style="text-align:left">Must be a syntactically valid object path</td>
</tr>
<tr>
<td style="text-align:left">SIGNATURE</td>
<td style="text-align:center">g (103)</td>
<td style="text-align:left">Zero or more single complete types</td>
</tr>
</tbody>
</table>
</li>
<li>
<p>结构 struct 的定义</p>
<ul>
<li>和上面的基本类型一样，struct 也以一个类型代码，为 &lsquo;r&rsquo;，但在实际表达上通常用括号 &ldquo;( )&rdquo; 表达；</li>
<li><code>(ii)</code> 表示有两个整数类型的结构；
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int32_t</span> <span class="n">a</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int32_t</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>在结构中还可以嵌套另一个结构，比如：&quot;(i(ii))&quot; 表示：
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int32_t</span> <span class="n">a</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int32_t</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int32_t</span> <span class="n">c</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="n">d</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>尽管结构在表达上并不使用其类型代码 &lsquo;r&rsquo;，但是在编程中，当你要获取一个数据的类型，而这个数据正好是一个结构时，函数会返回 &lsquo;r&rsquo;；</li>
</ul>
</li>
<li>
<p>数组 array 的定义</p>
<ul>
<li>数组的类型代码为 &lsquo;a&rsquo;，<code>ai</code> 表示一个整数数组，相当于 <code>int a[]</code></li>
<li>也可以定义一个结构数组，比如：<code>a(ii)</code> 表示一个有两个整数的结构数组，相当于：
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int32_t</span> <span class="n">a</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int32_t</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="n">c</span><span class="p">[];</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
</li>
<li>
<p>有了上面的介绍，应该可以看懂方法的定义了：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ResolveHostname(in  i ifindex,
</span></span><span class="line"><span class="cl">                in  s name,
</span></span><span class="line"><span class="cl">                in  i family,
</span></span><span class="line"><span class="cl">                in  t flags,
</span></span><span class="line"><span class="cl">                out a(iiay) addresses,
</span></span><span class="line"><span class="cl">                out s canonical,
</span></span><span class="line"><span class="cl">                out t flags);
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>&lsquo;in&rsquo; 表示调用该方法时的输入参数，&lsquo;out&rsquo; 表示该方法返回的参数；</li>
<li>所以这个方法调用时有四个输入参数，有三个返回参数，下面对输入和输出参数作出详细说明；</li>
</ul>
</li>
<li>
<p>调用参数：</p>
<table>
<thead>
<tr>
<th style="text-align:center">序号</th>
<th style="text-align:left">字段名称</th>
<th style="text-align:center">字段类型</th>
<th style="text-align:left">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">1</td>
<td style="text-align:left">ifindex</td>
<td style="text-align:center">int32_t</td>
<td style="text-align:left">网络接口索引号</td>
</tr>
<tr>
<td style="text-align:center">2</td>
<td style="text-align:left">name</td>
<td style="text-align:center">char *</td>
<td style="text-align:left">主机名</td>
</tr>
<tr>
<td style="text-align:center">3</td>
<td style="text-align:left">family</td>
<td style="text-align:center">int32_t</td>
<td style="text-align:left">地址族</td>
</tr>
<tr>
<td style="text-align:center">4</td>
<td style="text-align:left">flags</td>
<td style="text-align:center">uint64_t</td>
<td style="text-align:left">标志</td>
</tr>
</tbody>
</table>
<ul>
<li>ifindex：网络接口索引号，如果不知道使用那个网络接口，可以填 0，表示任何接口都可以，函数 <code>if_indextoname()</code> 可以把网络接口索引号转换成网络接口名称，<code>if_nametoindex()</code> 可以把网络接口名称转换成网络接口索引号，比如网络接口 &ldquo;eth0&rdquo;，可以用 <code>if_nametoindex(&quot;eth0&quot;)</code> 将其转为网络接口索引号；</li>
<li>name：主机名，就是常说的域名，比如：<code>whowin.cn</code>、<code>www.baidu.com</code>、<code>google.com</code> 等；</li>
<li>family：地址族，常用的就两个：<code>AF_INET</code> 和 <code>AF_INET6</code>，前者表示 IPv4，后者表示 IPv6</li>
<li>如果不确定主机名有 IPv4 或者 IPv6 地址，可以将参数 family 设为 <code>AF_UNSPEC</code>，表示既可以是 IPv4 也可以是 IPv6，但是这个选项不会既有 IPv4 地址又有 IPv6 地址，它首先会尝试查找 IPv4 地址，如果找到，则不再查找 IPv6 地址，如果没有找到，则尝试查找 IPv6 地址；</li>
<li>flags：标志，通常设置为 0 即可，如果希望了解这个标志的详情，可以在 <a href="https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.resolve1.html">systemd-resolve 官方文档</a> 中找到，但在一般的应用中，可以不考虑这个参数；</li>
</ul>
</li>
<li>
<p>返回参数：</p>
<table>
<thead>
<tr>
<th style="text-align:center">序号</th>
<th style="text-align:left">字段名称</th>
<th style="text-align:center">字段类型</th>
<th style="text-align:left">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">1</td>
<td style="text-align:left">addresses</td>
<td style="text-align:center">数组</td>
<td style="text-align:left">地址</td>
</tr>
<tr>
<td style="text-align:center">2</td>
<td style="text-align:left">caonical</td>
<td style="text-align:center">char *</td>
<td style="text-align:left">规范的主机名</td>
</tr>
<tr>
<td style="text-align:center">3</td>
<td style="text-align:left">flags</td>
<td style="text-align:center">uint64_t</td>
<td style="text-align:left">标志</td>
</tr>
</tbody>
</table>
<ul>
<li>
<p>返回参数的第一项要复杂一些，我们先说后面两项；</p>
</li>
<li>
<p>canonical：规范的主机名，这个主机名和调用时的主机名可能是一样的，也有可能不同；</p>
</li>
<li>
<p>flags：这个标志与调用时的标志相似，可以不用管它，或者在 <a href="https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.resolve1.html">systemd-resolve 官方文档</a> 中查找其详细说明；</p>
</li>
<li>
<p>回过头来说返回参数的第一项，当我们解析一个域名时，这个域名可能有不止一个 IP 地址，所以，解析结果是一个数组，数组中的每一项代表一个解析结果；</p>
</li>
<li>
<p>这个数组时这样定义的 <code>a(iiay)</code>，这意味着这是一个结构数组，结构是由两个整数和一个数组组成，这个数组是一个 <code>uint8_t</code> 的数组，整个下来应该是下面这样：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">address</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int32_t</span> <span class="n">ifindex</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int32_t</span> <span class="n">sa_family</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint8_t</span> <span class="n">ip</span><span class="p">[</span><span class="n">INET6_ADDRSTRLEN</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">address</span> <span class="o">*</span><span class="n">addresses</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>ifindex：接口的索引号，这个和输入参数的接口索引号是一个意思；</p>
</li>
<li>
<p>sa_family：表示当前地址的类型，<code>AF_INET</code> 表示是 IPv4 地址，<code>AF_INET6</code> 表示是 IPv6 地址；</p>
</li>
<li>
<p>其中，数组 ip 的长度取决于 <code>sa_family</code> 的值，当 <code>sa_family</code> 为 <code>AF_INET</code> 时，数组 ip 的长度为 4，当 <code>sa_family</code> 为 <code>AF_INET6</code> 时，数组 ip 的长度为 16；</p>
</li>
</ul>
</li>
<li>
<p>至此，对这个系统调用的方法已经介绍完了，剩下的就是实践了。</p>
</li>
</ul>
<h2 id="3-libdbus-中相关函数介绍">3 libdbus 中相关函数介绍</h2>
<ul>
<li>实例中的大部分函数都已经在文章 <a href="https://whowin.gitee.io/post/blog/ipc/0021-ipc-using-dbus/">《IPC之十一：使用D-Bus实现客户端向服务端请求服务的实例》</a> 和 <a href="https://whowin.gitee.io/post/blog/ipc/0022-dbus-asyn-process-signal/">《IPC之十二：使用libdbus在D-Bus上异步发送/接收信号的实例》</a> 中做了介绍，再次建议在阅读本文之前阅读上述两篇文章；</li>
<li>这里仅介绍在上述两篇文章中没有介绍的函数；</li>
</ul>
<h3 id="函数-dbus_message_iter_init在一个消息上初始化一个迭代器">函数 <code>dbus_message_iter_init()</code>：在一个消息上初始化一个迭代器</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="n">dbus_bool_t</span> <span class="n">dbus_message_iter_init</span><span class="p">(</span><span class="n">DBusMessage</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                    <span class="n">DBusMessageIter</span> <span class="o">*</span><span class="n">iter</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>迭代器的概念多出现在面向对象的编程语言中，比如 C++、JAVA，用于遍历一个对象，这里的迭代器用于遍历整个参数；</li>
<li>在前两篇文章中，介绍过函数 <code>dbus_message_get_args()</code>，当返回参数中没有数组和结构这种复杂类型，都是基本数据类型，比如：各种整数、字符串等都可以使用这个函数；</li>
<li>甚至于返回的数据为一个简单的数组，比如：<code>int32_t a[5]</code> 这样的数组也是可以用 <code>dbus_message_get_args()</code> 获取返回参数的；</li>
<li>但是 <code>ResolveHostname</code> 方法返回的数组中不仅有数组，还是一个结构数组，结构数组中还嵌套有另一个数组，这个过于复杂，创建一个迭代器来获取参数是个好的选择；</li>
<li><code>dbus_message_iter_init()</code> 在消息 message 上创建一个迭代器 iter，创建成功返回 TRUE，否则返回 FALSE；</li>
</ul>
<h3 id="函数-dbus_message_iter_recurse在迭代器上初始化一个子迭代器">函数 <code>dbus_message_iter_recurse()</code>：在迭代器上初始化一个子迭代器；</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">dbus_message_iter_recurse</span><span class="p">(</span><span class="n">DBusMessageIter</span> <span class="o">*</span><span class="n">iter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                <span class="n">DBusMessageIter</span> <span class="o">*</span><span class="n">sub</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>当消息参数中有数组或者结构时，需要使用迭代器去遍历参数中的各项，所以要在这个消息上建立一个迭代器；</li>
<li>当我们遍历参数中的各项时，如果又遇到数组或者结构，就需要在这个迭代器下建立一个子迭代器，用于遍历这个数组或者结构，以此类推；</li>
<li><code>dbus_message_iter_recurse()</code> 在迭代器 iter 指向的数组或结构上建立一个子迭代器 sub，用于遍历这个数组或者结构</li>
</ul>
<h3 id="函数-dbus_message_iter_get_arg_type获取迭代器指向的参数的参数类型">函数 <code>dbus_message_iter_get_arg_type()</code>：获取迭代器指向的参数的参数类型；</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">dbus_message_iter_get_arg_type</span><span class="p">(</span><span class="n">DBusMessageIter</span> <span class="o">*</span><span class="n">iter</span><span class="p">);</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>该函数可以获取迭代器指向的参数的数据类型，通常，如果数据类型为基本类型(不是数组、结构之类)，则可以用 <code>dbus_message_iter_get_basic()</code> 获取参数的值，如果数据类型是数组或者结构之类的类型，则不得不建立一个子迭代器去遍历其中的字段；</li>
<li>该函数返回数据类型，这些类型定义在头文件 <code>&lt;dbus/dbus-protocol.h&gt;</code> 中，是一系列的以 <code>&quot;DBUS_TYPE_&quot;</code> 开头的宏定义，一般一种类型有两个定义，一个是 <code>int</code> 的，还有一个是 <code>char *</code> 的，用于不同的场景，比如：32位整数的类型定义如下：
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="cm">/** Type code marking a 32-bit signed integer */</span>
</span></span><span class="line"><span class="cl"><span class="cp">#define DBUS_TYPE_INT32                 ((int) &#39;i&#39;)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cm">/** #DBUS_TYPE_INT32 as a string literal instead of a int literal */</span>
</span></span><span class="line"><span class="cl"><span class="cp">#define DBUS_TYPE_INT32_AS_STRING       &#34;i&#34;
</span></span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>值得一提的是，定义了一个 <code>DBUS_TYPE_INVALID</code>，其值为 <code>((int) '\0')</code>，这并不是一个实际的数据类型，这个定义用于标识一组参数的结束，当向一个消息中添加参数时，最后要添加一个 <code>DBUS_TYPE_INVALID</code>，当我们获取参数时，当遇到 <code>DBUS_TYPE_INVALID</code> 时，表示参数遍历完成；</li>
</ul>
<h3 id="函数-dbus_message_iter_get_basic从消息迭代器读取基本类型值">函数 <code>dbus_message_iter_get_basic()</code>：从消息迭代器读取基本类型值</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">dbus_message_iter_get_basic</span><span class="p">(</span><span class="n">DBusMessageIter</span> <span class="o">*</span><span class="n">iter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                 <span class="kt">void</span> <span class="o">*</span><span class="n">value</span><span class="p">)</span>	
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><code>value</code> 参数应该是存储返回值的位置的地址，因此，对于 <code>int32</code> 来说，它应该是 <code>dbus_int32_t *</code>，对于 <code>string</code> 来说，它应该是 <code>const char **</code>，返回值是引用值，不要使用 <code>free()</code> 释放；</li>
<li>要注意的是，调用本函数前，一定要使用 <code>dbus_message_iter_get_arg_type()</code> 确定数据类型，确保 value 的数据类型是正确的，否则可能程序会崩溃，比如，返回值是一个字符串，而 <code>value</code> 的数据类型是 <code>int32</code>，大概率程序会崩溃；</li>
</ul>
<h3 id="函数-dbus_message_iter_next将迭代器移动到下一个字段">函数 <code>dbus_message_iter_next()</code>：将迭代器移动到下一个字段;</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="n">dbus_bool_t</span> <span class="nf">dbus_message_iter_next</span><span class="p">(</span><span class="n">DBusMessageIter</span> <span class="o">*</span><span class="n">iter</span><span class="p">);</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>使用迭代器遍历数组的时候，每处理完一个字段，都要使用这个函数使迭代器的指针指向下一个字段；</li>
<li>如果后面已经没有字段，该函数返回 FALSE，指针移动成功则返回 TRUE。</li>
</ul>
<h3 id="使用迭代器获取参数的步骤">使用迭代器获取参数的步骤</h3>
<pre><code>```C
DBusMessage *message;
......
DBusMessageIter iter;
dbus_message_iter_init(message, &amp;iter);
char arg_str[1024];
uint64_t arg_uint64;
do {
    int current_type = dbus_message_iter_get_arg_type(&amp;iter);
    if (current_type == DBUS_TYPE_STRING) {
        dbus_message_iter_get_basic(&amp;iter, &amp;arg_str);
        goto NEXT_ITEM;
    }
    if (current_type == DBUS_TYPE_UINT64) {
        dbus_message_iter_get_basic(&amp;iter, &amp;arg_uint64);
        goto NEXT_ITEM;
    }
    ......
    if (current_type == DBUS_TYPE_ARRAY) {
        DBusMessageIter array_iter;
        dbus_message_iter_recurse(&amp;iter, &amp;array_iter);
        do {
            ......
        } while (dbus_message_iter_next(&amp;array_iter));
    }
    if (current_type == DBUS_TYPE_STRUCT) {
        DBusMessageIter struct_iter;
        dbus_message_iter_recurse(&amp;iter, &amp;struct_iter);
        ......
        dbus_message_iter_next(&amp;struct_iter);
        ......
        dbus_message_iter_next(&amp;struct_iter);
        ......
    }
    ......
} while (dbus_message_iter_next(&amp;iter));
```
</code></pre>
<h2 id="4-域名解析实例">4 域名解析实例</h2>
<ul>
<li>
<p><strong>源程序</strong>：<a href="https://gitee.com/whowin/whowin/blob/blog/sourcecodes/190023/dbus-hostname.c">dbus-hostname.c</a>(<strong>点击文件名下载源程序，建议使用UTF-8字符集</strong>)演示了使用 libdbus 请求系统服务 <code>systemd-resolved</code> 实现域名解析的过程；</p>
</li>
<li>
<p>编译：<code>gcc -Wall -g dbus-hostname.c -o dbus-hostname `pkg-config --libs --cflags dbus-1` </code></p>
</li>
<li>
<p>有关 <code>pkg-config --libs --cflags dbus-1</code> 可以参阅文章 <a href="https://whowin.gitee.io/post/blog/ipc/0021-ipc-using-dbus/">《IPC之十一：使用D-Bus实现客户端向服务端请求服务的实例》</a> 中的简要说明；</p>
</li>
<li>
<p>该程序的使用方法：<code>./dbus-hostname &lt;主机名&gt; [地址族]</code>，主机名一定要有，地址族可以是 <code>AF_INET</code> 或者 <code>AF_INET6</code>，前者仅解析 IPv4 的 IP 地址，后者仅解析 IPv6 的 IP 地址，如果地址族没有填，则地址族设置为 <code>AF_UNSPEC</code>，其含义文中有介绍；</p>
</li>
<li>
<p>运行：<code>./dbus-hostname baidu.com</code> 或者 <code>./dbus-hostname baidu.com AF_INET6</code></p>
</li>
<li>
<p>运行截图：</p>
<p><img src="https://whowin.gitee.io/images/190023/screen-of-dbus-hostname.png" alt="Screenshot of running dbus-hostname"></p>
</li>
</ul>
<h2 id="欢迎订阅-进程间通信专栏httpsblogcsdnnetwhowincategory_12404164html"><strong>欢迎订阅 <a href="https://blog.csdn.net/whowin/category_12404164.html">『进程间通信专栏』</a></strong></h2>
<hr>
<p><strong>欢迎访问我的博客：https://whowin.cn</strong></p>
<p><strong>email: <a href="mailto:hengch@163.com">hengch@163.com</a></strong></p>
<p><img src="https://whowin.gitee.io/images/qrcode/sponsor-qrcode.png" alt="donation"></p>
<!-- for CSDN
[article01]: https://blog.csdn.net/whowin/article/details/132171311
[article02]: https://blog.csdn.net/whowin/article/details/132171930
[article03]: https://blog.csdn.net/whowin/article/details/132172172
[article04]: https://blog.csdn.net/whowin/article/details/134869490
[article05]: https://blog.csdn.net/whowin/article/details/134869636
[article06]: https://blog.csdn.net/whowin/article/details/134939609
[article07]: https://blog.csdn.net/whowin/article/details/135015196
[article08]: https://blog.csdn.net/whowin/article/details/135074991
[article09]: https://blog.csdn.net/whowin/article/details/135143545
[article10]: https://blog.csdn.net/whowin/article/details/135212050
[article11]: https://blog.csdn.net/whowin/article/details/135281195
[article12]: https://blog.csdn.net/whowin/article/details/135332257
[article13]: https://blog.csdn.net/whowin/article/details/135332658
-->
<!-- CSDN
[img01]: https://img-blog.csdnimg.cn/img_convert/e8ef158765dea0aa98b1d762427aaf3e.png
[img02]: https://img-blog.csdnimg.cn/img_convert/13d138d8c642f3cd049fbafa9474714b.png
-->
    </div>

    <div class="post-copyright">
  <p class="copyright-item">
    <span class="item-title">文章作者</span>
    <span class="item-content">whowin</span>
  </p>
  <p class="copyright-item">
    <span class="item-title">上次更新</span>
    <span class="item-content">
        2023-12-10
        
    </span>
  </p>
  
  
</div>
<footer class="post-footer">
      <div class="post-tags">
          <a href="/tags/linux/">Linux</a>
          <a href="/tags/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/">进程间通信</a>
          <a href="/tags/d-bus/">D-Bus</a>
          <a href="/tags/libdbus/">libdbus</a>
          <a href="/tags/ipc/">IPC</a>
          <a href="/tags/%E5%9F%9F%E5%90%8D%E8%A7%A3%E6%9E%90/">域名解析</a>
          <a href="/tags/systemd-resolved/">systemd-resolved</a>
          </div>
      <nav class="post-nav">
        <a class="prev" href="/post/blog/ipc/0024-select-recv-message/">
            <i class="iconfont icon-left"></i>
            <span class="prev-text nav-default">IPC之十四：使用libdbus通过select()接收D-Bus消息的实例</span>
            <span class="prev-text nav-mobile">上一篇</span>
          </a>
        <a class="next" href="/post/blog/ipc/0022-dbus-asyn-process-signal/">
            <span class="next-text nav-default">IPC之十二：使用libdbus在D-Bus上异步发送/接收信号的实例</span>
            <span class="next-text nav-mobile">下一篇</span>
            <i class="iconfont icon-right"></i>
          </a>
      </nav>
    </footer>
  </article>
        </div>
        

  <span id="/post/blog/ipc/0023-dbus-resolve-hostname/" class="leancloud_visitors" data-flag-title="IPC之十三：使用libdbus通过D-Bus请求系统调用实现域名解析的实例">
		<span class="post-meta-item-text">文章阅读量 </span>
		<span class="leancloud-visitors-count">0</span>
		<p></p>
	  </span>
  <div id="vcomments"></div>
  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  <script src='//unpkg.com/valine/dist/Valine.min.js'></script>
  <script type="text/javascript">
    new Valine({
        el: '#vcomments' ,
        appId: 'OFCGzCfJRUglzOdzrqMGkbTR-gzGzoHsz',
        appKey: 'v7P29kPAEbsmaavaYPNhGhnF',
        notify:  false ,
        verify:  false ,
        avatar:'mm',
        placeholder: '说点什么吧...',
        visitor:  true 
    });
  </script>

  

      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="social-links">
      <a href="mailto:hengch@163.com" class="iconfont icon-email" title="email"></a>
  <a href="https://whowin.gitee.io/index.xml" type="application/rss+xml" class="iconfont icon-rss" title="rss"></a>
</div>
<div class="copyright">
  <span class="power-by">
    由 <a class="hexo-link" href="https://gohugo.io">Hugo</a> 强力驱动
  </span>
  <span class="division">|</span>
  <span class="theme-info">
    主题 - 
    <a class="theme-link" href="https://github.com/olOwOlo/hugo-theme-even">Even</a>
  </span>

  <div class="busuanzi-footer">
    <span id="busuanzi_container_site_pv"> 本站总访问量 <span id="busuanzi_value_site_pv"><img src="/img/spinner.svg" alt="spinner.svg"/></span> 次 </span>
      <span class="division">|</span>
    <span id="busuanzi_container_site_uv"> 本站总访客数 <span id="busuanzi_value_site_uv"><img src="/img/spinner.svg" alt="spinner.svg"/></span> 人 </span>
  </div>

  <span class="copyright-year">
    &copy; 
    2022 - 
    2024<span class="heart"><i class="iconfont icon-heart"></i></span><span>whowin</span>
  </span>
</div>

    </footer>

    <div class="back-to-top" id="back-to-top">
      <i class="iconfont icon-up"></i>
    </div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/slideout@1.0.1/dist/slideout.min.js" integrity="sha256-t+zJ/g8/KXIJMjSVQdnibt4dlaDxc9zXr/9oNPeWqdg=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.1.20/dist/jquery.fancybox.min.js" integrity="sha256-XVLffZaxoWfGUEbdzuLi7pwaUJv1cecsQJQqGLe7axY=" crossorigin="anonymous"></script>



<script type="text/javascript" src="/js/main.min.64437849d125a2d603b3e71d6de5225d641a32d17168a58106e0b61852079683.js"></script>
  <script type="text/javascript">
    window.MathJax = {
      tex: {
        inlineMath: [['$','$'], ['\\(','\\)']],
        }
    };
  </script>
  <script async src="https://cdn.jsdelivr.net/npm/mathjax@3.0.5/es5/tex-mml-chtml.js" integrity="sha256-HGLuEfFcsUJGhvB8cQ8nr0gai9EucOOaIxFw7qxmd+w=" crossorigin="anonymous"></script>








</body>
</html>
